﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WiiGeeDotNet.events;

namespace WiiGeeDotNet.logic
{
  public class Gesture
  {
    /** Min/MaxAcceleration setup manually? */
    private bool m_minmaxmanual;
    private double m_minacc;
    private double m_maxacc;


    /** The complete trajectory as WiimoteAccelerationEvents
     * as a vector. It's a vector because we don't want to
     * loose the chronology of the stored events.
     */
    private List<AccelerationEvent> m_data;

    private DateTime m_created;
    public DateTime Created
    {
      get { return m_created; }
    }

    
    /**
     * Create an empty Gesture.
     */
    public Gesture()
    {
      m_data = new List<AccelerationEvent>();
      m_created = DateTime.Now;
    }

    /** 
     * Make a deep copy of another Gesture object.
     * 
     * @param original Another Gesture object
     */
    public Gesture(Gesture original): this()
    {
      List<AccelerationEvent> origin = original.GetData();
      for (int i = 0; i < origin.Count; i++)
      {
        this.Add((AccelerationEvent)origin[i]);
      }
    }


    /**
     * Adds a new acceleration event to this gesture.
     * 
     * @param event The WiimoteAccelerationEvent to add.
     */
    public void Add(AccelerationEvent _event)
    {
      this.m_data.Add(_event);


    }

    /**
     * Returns the last acceleration added to this gesture.
     * 
     * @return the last acceleration event added.
     */
    public AccelerationEvent GetLastData()
    {
      return (AccelerationEvent)this.m_data[this.m_data.Count - 1];
    }

    /**
     * Returns the whole chronological sequence of accelerations as
     * a vector.
     * 
     * @return chronological sequence of accelerations.
     */
    public List<AccelerationEvent> GetData()
    {
      return this.m_data;
    }

    /**
     * Removes the first element of the acceleration queue of a gesture
     */
    public void RemoveFirstData()
    {
      this.m_data.RemoveAt(0);
    }

    public int GetCountOfData()
    {
      return this.m_data.Count;
    }

    public void SetMaxAndMinAcceleration(double max, double min)
    {
      this.m_maxacc = max;
      this.m_minacc = min;
      this.m_minmaxmanual = true;
    }

    public double GetMaxAcceleration()
    {
      if (!this.m_minmaxmanual)
      {
        double maxacc = Double.MinValue;
        for (int i = 0; i < this.m_data.Count; i++)
        {
          if (Math.Abs(this.m_data[i].X) > maxacc)
          {
            maxacc = Math.Abs(this.m_data[i].X);
          }
          if (Math.Abs(this.m_data[i].Y) > maxacc)
          {
            maxacc = Math.Abs(this.m_data[i].Y);
          }
          if (Math.Abs(this.m_data[i].Z) > maxacc)
          {
            maxacc = Math.Abs(this.m_data[i].Z);
          }
        }
        return maxacc;
      }
      else
      {
        return this.m_maxacc;
      }
    }

    public double GetMinAcceleration()
    {
      if (!this.m_minmaxmanual)
      {
        double minacc = Double.MaxValue;
        for (int i = 0; i < this.m_data.Count; i++)
        {
          if (Math.Abs(this.m_data[i].X) < minacc)
          {
            minacc = Math.Abs(this.m_data[i].X);
          }
          if (Math.Abs(this.m_data[i].Y) < minacc)
          {
            minacc = Math.Abs(this.m_data[i].Y);
          }
          if (Math.Abs(this.m_data[i].Z) < minacc)
          {
            minacc = Math.Abs(this.m_data[i].Z);
          }
        }
        return minacc;
      }
      else
      {
        return this.m_minacc;
      }
    }
  }
}
